package cn.com.egova.bouncingmenu;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by yuanchao on 2017/4/16.
 */

public class BouncingView extends View {
    private Context mContext;
    private int mArcHeight;
    private int mMaxArcHeight;
    private int mWidth;
    private int mHeight;
    private Paint mPaint;
    private int bgColor;
    private Path mPath;
    private Status mStatus = Status.NONE;
    private OnStatusChangeListener mOnStatusChangeListener;
    private int mDelayTimeMillis;

    public BouncingView(Context context) {
        this(context, null);
    }

    public BouncingView(Context context,int maxArcHeight,int bgColor) {
        super(context);
        this.mMaxArcHeight = maxArcHeight;
        this.bgColor = bgColor;
        init();
    }

    public BouncingView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BouncingView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        setCustomAttributes(attrs);
        init();
    }

    private void setCustomAttributes(AttributeSet attrs) {
        TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.bouncingView);
        mMaxArcHeight = typedArray.getDimensionPixelOffset(R.styleable.bouncingView_maxArcHeight, 100);
        bgColor = typedArray.getColor(R.styleable.bouncingView_bouncingbg,Color.WHITE);
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setColor(bgColor);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setAntiAlias(true);
        mPath = new Path();
    }


    public int getMaxArcHeight() {
        return mMaxArcHeight;
    }

    public int getBgColor() {
        return bgColor;
    }

    public void setOnStatusChangeListener(OnStatusChangeListener listener) {
        this.mOnStatusChangeListener = listener;
    }

    public int getDelayTimeMillis() {
        return mDelayTimeMillis;
    }

    public void setDelayTimeMillis(int delayTimeMillis) {
        this.mDelayTimeMillis = delayTimeMillis;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //onMeasure方法之后,getWidth(),getHeight()就能拿到正确的值了.
        mWidth = getWidth();
        mHeight = getHeight();

        int curPointY = 0;
        switch (mStatus) {
            case NONE:
                curPointY = 0;
                break;
            case STATUS_SMOOTH_UP:
                //1.注意贝塞尔曲线的锚点(弧线中心点)的当前高度与curPointY之间的关系;
                // 2.绘制Veiw时,绘制的过程中涉及到的坐标,是指View的内容相对于View左上角顶点的坐标.
                //mArcHeight/mMaxArcHeight = (getHeight()-curPointY)/getHeight();
                //3.最后面+mMaxArcHeight的目的是,将y值向下偏移maxArcHeight,否则在最高点时,弧线将显示不出来,因为超出了view的范围.
                curPointY = (int) (mHeight - ((float) mArcHeight / mMaxArcHeight) * mHeight) + mMaxArcHeight;
                break;
            case STATUS_BOUNCE_DOWN:
                //注意由于y值往下偏移了maxArcHeight距离,所以y的取值范围变成了(maxArcHeight,mHeight+maxArcHeight)
                curPointY = mMaxArcHeight;
                break;
        }

        mPath.reset();
        mPath.moveTo(0, curPointY);
        mPath.quadTo(mWidth / 2, curPointY - mArcHeight, mWidth, curPointY);
        mPath.lineTo(mWidth, mHeight);
        mPath.lineTo(0, mHeight);
        mPath.close();

        canvas.drawPath(mPath, mPaint);
    }


    public void show() {
        mStatus = Status.STATUS_SMOOTH_UP;
        ValueAnimator animator = ValueAnimator.ofFloat(0, mMaxArcHeight);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (Float) animation.getAnimatedValue();
                mArcHeight = (int) value;
                invalidate();
                //到最高点后往下回弹.
                if (mArcHeight == mMaxArcHeight) {
                    bounceBack();
                }
            }
        });
        animator.setDuration(700);
        animator.start();

        //可以给点视差效果,即运动到一定高度再显示其他View.
        //view也有postDelay方法!!!
        if(mOnStatusChangeListener!=null){
            this.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mOnStatusChangeListener.onStatusChange(BouncingView.this,mStatus);
                }
            },mDelayTimeMillis);
        }
    }


    private void bounceBack() {
        mStatus = Status.STATUS_BOUNCE_DOWN;
        ValueAnimator animator = ValueAnimator.ofFloat(mMaxArcHeight, 0);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (Float) animation.getAnimatedValue();
                mArcHeight = (int) value;
                invalidate();

                //回弹结束.
                if(mArcHeight==0){
                    if(mOnStatusChangeListener!=null){
                        mOnStatusChangeListener.onStatusChange(BouncingView.this,mStatus);
                    }
                }
            }
        });
        animator.setDuration(200);
        animator.start();
    }

    /**
     * BouncingView当前的运动状态.
     */
    public enum Status {
        NONE, STATUS_SMOOTH_UP, STATUS_BOUNCE_DOWN;
    }


    public interface OnStatusChangeListener{
        void onStatusChange(BouncingView bv,Status status);
    }
}
